package ca.etsmtl.log430.lab1;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PipedWriter;

/**************************************************************************************
 ** Class name: MainFilter Original author: A.J. Lattanze, CMU Date: 12/3/99
 * Version 1.0
 ** 
 ** Adapted by R. Champagne, Ecole de technologie superieure 2002-May-08,
 * 2011-Jan-12.
 ** 
 *************************************************************************************** 
 ** Purpose: Assignment 1 for LOG430, Architecture logicielle. This assignment is
 * designed to illustrate a pipe and filter architecture. For the instructions,
 * refer to the assignment write-up.
 ** 
 ** Abstract: This class contains the main method for assignment 1. The
 * assignment 1 program consists of 5 files:
 ** 
 ** 1) MainFilter: starts all filters, reads each student entry from the input
 * file and sends it to its output stream. 2) ProgramFilter: separates the LOG
 * students from CGL students and writes them to the appropriate output pipe. 3)
 * CourseFilter: determines if a student entry has taken a particular course
 * that is specified during instantiation. 4) MergeFilter: accepts input from 2
 * input pipes and writes it to its output pipe. 5) FileWriterFilter: sends its
 * input stream to a text file.
 ** 
 ** Pseudo Code:
 ** 
 ** start ProgramFilter start CourseFilter for LOG120 start CourseFilter for
 * CGL200 start MergeFilter start FileWriterFilter
 ** 
 ** open input file provided on command line
 ** 
 ** while not eof (input file) read line of text write line of text to output
 * pipe end while
 ** 
 ** close pipes and files
 ** 
 ** Running the program
 ** 
 ** Java MainFilter IputFile OutputFile > ListingFile
 ** 
 ** MainFilter - Program name InputFile - Text input file (see comments below)
 * OutputFile - Text output file with students ListingFile - Optional file to
 * direct debug statements
 ** 
 ** Modification Log
 ************************************************************************************** 
 ** 
 **************************************************************************************/

public class MainFilter {

	public static void main(String argv[]) {
		// Lets make sure that input and output files are provided on the
		// command line

		if (argv.length != 3) {

			System.out
					.println("\n\nNombre incorrect de parametres d'entree. Utilisation:");
			System.out
					.println("\njava MainFilter <fichier d'entree> <fichier de sortie success> <fichier de sortie fail>");

		} else {

			// Declarations:

			String LineOfText;
			File InputFile = new File(argv[0]);

			// These are the declarations for the pipes.
			PipedWriter pipeMainFilterToProgramFilter = new PipedWriter();

			PipedWriter pipeLogToMat210 = new PipedWriter(); // first course
																// FILTER FOR
																// LOG STUDENT
			
			PipedWriter pipeCGLToCGL110 = new PipedWriter(); // first course
																// FILTER FOR
																// CGL STUDENT

			PipedWriter pipeCGL110ToMat210 = new PipedWriter();
			PipedWriter pipeCGL110ToMergeFail = new PipedWriter();

			// common pipe
			PipedWriter pipeMat210ToMat205 = new PipedWriter();

			PipedWriter pipeMat210ToMergeSuccess = new PipedWriter();
			PipedWriter pipeMat205ToMergeSuccess = new PipedWriter();
			PipedWriter pipeToMat205MergeFail = new PipedWriter();

			PipedWriter pipeToFichierSuccess = new PipedWriter();
			PipedWriter pipeToFichierFail = new PipedWriter();

			// Instantiate the Program Filter Thread
			Thread ProgramFilter1 = new ProgramFilter(pipeMainFilterToProgramFilter, pipeLogToMat210,pipeCGLToCGL110);

			// Instantiate the Course Filter Threads
			Thread CourseFilter1 = new CourseFilter("MAT210", pipeLogToMat210, pipeCGL110ToMat210, pipeMat210ToMergeSuccess, pipeMat210ToMat205);			
			Thread CourseFilter2 = new CourseFilter("MAT205", pipeMat210ToMat205, pipeMat205ToMergeSuccess, pipeToMat205MergeFail);			
			Thread CourseFilter3 = new CourseFilter("CGL110", pipeCGLToCGL110, pipeCGL110ToMat210, pipeCGL110ToMergeFail);

			// Instantiate the Merge Filter Thread
			Thread MergeFilterSuccess = new MergeFilter(pipeMat210ToMergeSuccess, pipeMat205ToMergeSuccess,pipeToFichierSuccess);
			Thread MergeFilterFail = new MergeFilter(pipeToMat205MergeFail, pipeCGL110ToMergeFail, pipeToFichierFail);

			// Instantiate the FileWriter Filter Thread
			Thread FileWriterFilterSuccess = new FileWriterFilter(argv[1], pipeToFichierSuccess);
			Thread FileWriterFilterFail = new FileWriterFilter(argv[2], pipeToFichierFail);

			// Start the threads (these are the filters)
			ProgramFilter1.start();

			CourseFilter1.start();
			CourseFilter2.start();
			CourseFilter3.start();

			MergeFilterSuccess.start();
			MergeFilterFail.start();

			FileWriterFilterSuccess.start();
			FileWriterFilterFail.start();

			// Open input file. The input file is a field oriented and
			// space-separated.
			// The fields are as follows:
			//
			// Student ID Student's Program Course numbers that the student
			// Last Name Acronym has completed with no hyphens
			//
			// Here is an example:
			//
			// FRAE230679 Franklin LOG LOG120 MAT115 CHM100 COM110

			// Check to ensure that the file exists

			if (!InputFile.exists()) {

				System.out.println("\nMainFilter:: file "
						+ InputFile.getAbsolutePath() + " does not exist.");

			} else {

				System.out.println("MainFilter:: file "
						+ InputFile.getAbsolutePath() + " opened.");

				try {
					// Create a buffered reader the file
					BufferedReader InFile = new BufferedReader(
							new InputStreamReader(new FileInputStream(
									(InputFile))));

					// Read each line of text

					boolean Done = false;

					while (!Done) {

						// Read a line of text from the input file and convert
						// it to upper case

						LineOfText = InFile.readLine();

						if (LineOfText == null) {

							Done = true;

						} else {

							LineOfText.toUpperCase();

							System.out.println("MainFilter:: read: "
									+ LineOfText);

							try {

								// write line of text to the pipe
								pipeMainFilterToProgramFilter.write(LineOfText,
										0, LineOfText.length());
								pipeMainFilterToProgramFilter.write((int) '\n');
								// signals end of line
								pipeMainFilterToProgramFilter.flush();
								System.out.println("MainFilter:: wrote: "
										+ LineOfText + " to output pipe.");

							} catch (Exception Error) {

								System.out
										.println("MainFilter:: Error writing to pipe01.");
							} // try/catch

						} // if

					} // while

					// Close the input file

					InFile.close();
					System.out.println("\nMainFilter:: closing "
							+ InputFile.getAbsolutePath());

				} // try

				catch (Exception Error) {

					System.out
							.println("MainFilter:: Unable to create file stream");

				} // catch

			} // if

			try {

				pipeMainFilterToProgramFilter.close();

				System.out.println("MainFilter:: output pipe closed.");

			} catch (Exception Error) {

				System.out.println("MainFilter:: Error closing pipes.");

			} // try/catch

		} // if
		//System.exit(0);
	} // main
	
} // MainFilter